﻿using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using Serilog;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Chaunce.Web.Core;
using System.IO;
using System.Text;
using System.Net;
using Microsoft.AspNetCore.Http.Internal;
using System.Collections.Generic;
using Chaunce.FrameWork.NetCore.SysCore.Infrastructure;
using Chaunce.FrameWork.NetCore.SysCore.Configuration;
using Chaunce.FrameWork.NetCore.SysCore;
using Chaunce.FrameWork.NetCore.Utility.Exceptions;

namespace Chaunce.Web.Core.Infrastructure.Extensions
{
    /// <summary>
    ///IApplicationBuilder扩展
    /// </summary>
    public static class ApplicationBuilderExtensions
    {
        /// <summary>
        /// 配置http 请求管道
        /// </summary>
        /// <param name="application">Builder for configuring an application's request pipeline</param>
        public static void ConfigureRequestPipeline(this IApplicationBuilder application)
        {
            EngineContext.Current.ConfigureRequestPipeline(application);
        }

        /// <summary>
        /// Add exception handling
        /// </summary>
        /// <param name="application">Builder for configuring an application's request pipeline</param>
        public static void UseChaunceExceptionHandler(this IApplicationBuilder application)
        {
            //使用ChaunceExceptionFilter过滤器捕获异常信息
            return;
            #region
            var config = EngineContext.Current.Resolve<ChaunceConfig>();
            var hostingEnvironment = EngineContext.Current.Resolve<IHostingEnvironment>();
            var useDetailedExceptionPage = config.DisplayFullErrorStack || hostingEnvironment.IsDevelopment();
            if (useDetailedExceptionPage)
            {
                //get detailed exceptions for developing and testing purposes
               // application.UseDeveloperExceptionPage();
            }
            else
            {
                // application.UseExceptionHandler();
                //or use special exception handler
                // application.UseExceptionHandler("/errorpage.htm");
            }
            
            //全局异常捕获
            application.UseExceptionHandler(handler =>
            {
                handler.Run(async context =>
                {
                    var exception = context.Features.Get<IExceptionHandlerFeature>()?.Error;
                    if (exception != null)
                    {
                        context.Response.StatusCode = 200;
                        context.Response.ContentType = "application/json";
                        string errorMsg = "程序访问异常,请稍后重试！";

                        string requestBodyText = string.Empty;
                        var request = context.Request;
                        var method = request.Method.ToUpper();
                        #region 获取body参数
                        if (method == "POST" || method == "PUT" || method == "DELETE")
                        {
                            var collection = request.Form;
                            if (collection != null && collection.Count > 0)
                            {
                                //表单提交获取请求值 AddParameter
                                List<string> reqParams = new List<string>();
                                foreach (string key in collection.Keys)
                                {
                                    reqParams.Add(string.Format("{0}={1}", key, collection[key]));
                                }
                                requestBodyText = string.Join("&", reqParams);
                            }
                            else
                            {
                                if (request.Body.Length > 0)
                                {
                                    //request body 字符串+json 请求获取参数 
                                    request.EnableRewind();
                                    request.Body.Position = 0;
                                    using (StreamReader reader = new StreamReader(request.Body, Encoding.UTF8))
                                    {
                                        requestBodyText = reader.ReadToEnd();
                                    }
                                }
                            }
                        }
                        #endregion
                        int errorCode = 1;
                        string requestId = string.Empty;

                        if (exception is ChaunceException)
                        {
                            var ChaunceEx = (ChaunceException)exception;
                            errorMsg = ChaunceEx.Message;
                            errorCode = ChaunceEx.ErrorCode;
                            requestId = ChaunceEx.RequestId;
                        }
                        //写入日志系统
                        var url = string.Format("{0}{1}", request.Host.Value, request.Path.Value);
                        var requestIp = EngineContext.Current.Resolve<IWebHelper>().GetCurrentIpAddress();
                        Log.Error(exception, "WebApi异常.errorCode:{0},requestId:{1},请求url:{2},参数:{3},IP:{4}", errorCode, requestId, url, requestBodyText, requestIp);
                        //自定义异常返回
                        await context.Response.WriteAsync(errorMsg.ToErrorApiJson(errorCode)).ConfigureAwait(false);
                    }
                });
            });
            #endregion
        }

        /// <summary>
        /// Adds a special handler that checks for responses with the 404 status code that do not have a body
        /// </summary>
        /// <param name="application">Builder for configuring an application's request pipeline</param>
        public static void UsePageNotFound(this IApplicationBuilder application)
        {
            application.UseStatusCodePages(async context =>
            {
                //handle 404 Not Found
                if (context.HttpContext.Response.StatusCode == StatusCodes.Status404NotFound)
                {
                    var webHelper = EngineContext.Current.Resolve<IWebHelper>();
                    if (!webHelper.IsStaticResource())
                    {
                        //get original path and query
                        var originalPath = context.HttpContext.Request.Path;
                        var originalQueryString = context.HttpContext.Request.QueryString;

                        //store the original paths in special feature, so we can use it later
                        context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature()
                        {
                            OriginalPathBase = context.HttpContext.Request.PathBase.Value,
                            OriginalPath = originalPath.Value,
                            OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,
                        });

                        //get new path
                        context.HttpContext.Request.Path = "/page-not-found";
                        context.HttpContext.Request.QueryString = QueryString.Empty;

                        try
                        {
                            //re-execute request with new path
                            await context.Next(context.HttpContext);
                        }
                        finally
                        {
                            //return original path to request
                            context.HttpContext.Request.QueryString = originalQueryString;
                            context.HttpContext.Request.Path = originalPath;
                            context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(null);
                        }
                    }
                }
            });
        }

        /// <summary>
        /// Adds a special handler that checks for responses with the 400 status code (bad request)
        /// </summary>
        /// <param name="application">Builder for configuring an application's request pipeline</param>
        public static void UseBadRequestResult(this IApplicationBuilder application)
        {
            application.UseStatusCodePages(context =>
            {
                //handle 404 (Bad request)
                if (context.HttpContext.Response.StatusCode == StatusCodes.Status400BadRequest)
                {
                    Log.Fatal("页面访问404错误.{url}",context.HttpContext.Request.Path.ToString());
                }
                return Task.CompletedTask;
            });
        }

       
      

        /// <summary>
        /// Create and configure MiniProfiler service
        /// </summary>
        /// <param name="application">Builder for configuring an application's request pipeline</param>
        public static void UseMiniProfiler(this IApplicationBuilder application)
        {


        }

        
    }
}
